package dawn.net;

import java.util.concurrent.TimeoutException;

import org.apache.mina.core.session.IoSession;

import dawn.core.dispatch.Invoker;

/**
 * Remote Procedure Call Protocol
 * @author huangxiao
 */
public class RpcRequest extends Message implements Invoker<RpcResponse> {

	private int sequence;
	private RpcResponse result;
	private boolean completed;

	public RpcRequest() {
		setType(MessageType.RPC_REQUEST);
	}

	public int getSequence() {
		return sequence;
	}

	public void setSequence(int sequence) {
		this.sequence = sequence;
	}

	/**
	 * 同步调用
	 * @param session
	 * @return
	 * @throws Exception
	 */
	public synchronized RpcResponse invoke(IoSession session) throws Exception {
		RpcManager.getInstance().addListener(this.getSequence(), this);
		session.write(getData());
		return getResult();
	}

	/**
	 * 异步调用
	 * @param session
	 * @return
	 * @throws Exception
	 */
	public void invoke(IoSession session, ResultProcessor processor) throws Exception {
		session.write(getData());
		processor.onResponse(getResult());
	}

	public synchronized void setResult(RpcResponse result) {
		this.result = result;
		this.completed = true;
		this.notifyAll();
	}

	public synchronized RpcResponse getResult() throws Exception {
		if (!this.completed) {
			this.wait(5000);
			if (!this.completed)
				throw new TimeoutException();
		}
		return this.result;
	}

	@Override
	public Object handle(RpcResponse event) {
		this.setResult(event);
		return null;
	}

}
